#ifndef SXMEM_H
#define SXMEM_H

#include <iostream>

namespace sx
{

class CTest
{
public:
    CTest():
        mCount(0), mAllocs(0), mDeallocs(0)
    {
        std::cerr << "TEST BEGIN!" << std::endl;
    }
    ~CTest()
    {
        std::cerr << "TEST END!"  << std::endl;

        std::cerr << "Allocs: " << mAllocs << std::endl;
        std::cerr << "Deallocs: " << mDeallocs << std::endl;
        if (mCount > 0)
            std::cerr << "MemTest: negative count!" << std::endl;
    }

    void incCount()
    {
        mCount++;
        mAllocs++;
    }

    void decCount()
    {
        mCount--;
        mDeallocs++;
        if (mCount < 0)
            std::cerr << "MemTest: negative count!" << std::endl;
    }
private:
    int mCount;
    int mAllocs;
    int mDeallocs;
};

typedef unsigned int REFCOUNTER , *PREFCOUNTER;

class SxRefCounter
{
public:
    SxRefCounter(): mpCounter(0) { incCount(); }
    
    SxRefCounter(const SxRefCounter& RefCounter)
        : mpCounter(RefCounter.mpCounter)
        { incCount(); }
    
    ~SxRefCounter() { decCounter(); }

    void operator= (const SxRefCounter& Ref) 
    {
        if (this != &Ref)
        {
            decCounter();
            mpCounter = Ref.mpCounter;
            incCount();
        }
    }

    operator REFCOUNTER() { return *mpCounter; }
private:
    void incCount()
    {
        if (mpCounter)
            (*mpCounter)++;
        else
        {
            mpCounter = new REFCOUNTER;
            *mpCounter = 1;
        }
    }
    void decCounter()
    {
        (*mpCounter)--;
        if (*mpCounter == 0)
        {
            delete mpCounter;
            mpCounter = 0;
        }
    }
    PREFCOUNTER mpCounter;
};

class SxSharedBuffer
{
public:
    SxSharedBuffer(unsigned int Size=0);
    SxSharedBuffer(const SxSharedBuffer& Buff);
    SxSharedBuffer(const SxSharedBuffer& Buff, int Offset);
    ~SxSharedBuffer();
    SxSharedBuffer& operator= (const SxSharedBuffer&);

    template<class T>
    operator T*() { return reinterpret_cast<T*>(mPtr); }
    template<class T>
    operator const T*() const { return reinterpret_cast<const T*>(mPtr); }

    void setOffset(int Offset) { mPtr = reinterpret_cast<char*>(mBasePtr) + Offset; }
    int getSize() const { return mSize; }

private:
    void* mBasePtr;
    void* mPtr;
    int   mSize;
    SxRefCounter mRef;
};

}  //  namespace sx

#endif // SXMEM_H
